package tang.server;

import tang.server.processor.PreRequestProcessor;

import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author Tang
 * @classname NIOServerCnxn
 * @description [  ]
 * @date 2021/3/1 21:27
 */
public class NIOServerCnxn {

    private ZkServer zkServer;

    private SelectionKey selectionKey;

    private SocketChannel socketChannel;

    /**
     * 写操作使用的
     */
    private LinkedBlockingQueue<Request> blockingQueue = new LinkedBlockingQueue<>(8);

    private ByteBuffer lenBuffer = ByteBuffer.allocate(4);
    private ByteBuffer dataBuffer = lenBuffer;

    public NIOServerCnxn(ZkServer zkServer,SelectionKey selectionKey,SocketChannel socketChannel) throws Exception {
        this.zkServer = zkServer;
        this.selectionKey = selectionKey;
        this.socketChannel = socketChannel;

        this.socketChannel.socket().setTcpNoDelay(true);
        this.socketChannel.socket().setSoLinger(false,-1);

        selectionKey.interestOps(SelectionKey.OP_READ);
    }

    public void doIO(SelectionKey selectionKey) {
        // 读操作
        if (selectionKey.isReadable()) {
            try {
                this.socketChannel.read(dataBuffer);
                dataBuffer.flip();
                if (dataBuffer == lenBuffer) {
                    // 读长度
                    readLength();
                }else {
                    // 读数据
                    readData();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 写操作
        if (selectionKey.isWritable()) {

        }
    }

    private void readData() throws InterruptedException {
        Request request = new Request();
        int type = dataBuffer.getInt();
        request.setType(type);
        switch (type) {
            case 1:
                System.out.println("操作类型:server connect....");
                break;
            case 2:
                System.out.println("操作类型:server create....");
                break;
            default:
                break;
        }
        byte[] bytes = new byte[dataBuffer.capacity()];
        dataBuffer.get(bytes,dataBuffer.position(),dataBuffer.limit() - dataBuffer.position());
        request.setMessage(new String(bytes));
        dataBuffer.clear();
        // 写进 outgoingBlockQueue
        addProcessorRequest(request);
    }

    private void addProcessorRequest(Request request) {
        PreRequestProcessor preRequestProcessor = (PreRequestProcessor)this.zkServer.getFirstProcessor();
        preRequestProcessor.addProcessorRequest(request);
    }

    private void readLength() {
        int len = this.dataBuffer.getInt();
        this.dataBuffer = ByteBuffer.allocate(len);
    }
}